
#include "../../Command.h"

#include "../../User.h"
#include "../../NLogic/Static.h"
#include "../../NResource/Static.h"

#include <map>
#include <vector>

namespace ProjectZ { namespace NCommand {

static void SendAckFail(User * pUser, int16_t ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	* pAck << static_cast<int16_t>(ack) << static_cast<uint32_t>(0) << static_cast<uint8_t>(0) << static_cast<uint8_t>(0);
	pAck->MakePacket(CMD_SC_REQ_DUNGEON_PARTY_JOIN);
	pUser->Send(pAck);
}

void Command::CS_REQ_DUNGEON_PARTY_JOIN(User * pUser, ::Network::Packet *pPacket)
{
	/*\
	 * CS_REQ_DUNGEON_PARTY_JOIN	0x1129
	{
		u32 u32room_number;
		u16 u16dungeon_tid;
		u8 u8difficulty;
	}

	SC_REQ_DUNGEON_PARTY_JOIN	0x112A
	{
		s16 sAck;					/// 이미 시작된 파티 등의 ack값 ACK_START_BATTLE, ACK_NOT_PARTY
		u32 u32room_number;
		u8 u8party_member_num;		/// min 2 , max 3 본인 포함
		u8 count;					/// ack 1이 아닌경우 0 그외 파티원 수만큼  방장을 가장 앞에 넣어 주세요...
		{
			u32 u32gid;				/// 본인을 포함한 파티원 gid정보
		}
	}
	 *
	 */

	NLogic::Space * pWorld = pUser->GetSpace();
	if (NULL == pWorld)
	{
		DEBUGLOG("CS_REQ_DUNGEON_PARTY_JOIN NULL == pWorld");
		SendAckFail(pUser, ACK_NO_SPACE);
		return;
	}

	if (pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		DEBUGLOG("CS_REQ_DUNGEON_PARTY_JOIN pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD");
		SendAckFail(pUser, ACK_NO_SPACE);
		return;
	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		DEBUGLOG("CS_REQ_DUNGEON_PARTY_JOIN pUser->GetEnumState() != User::EnumState::__NONE__");
		SendAckFail(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	PREPARE_PACKET;

	uint32_t u32room_number = 0;
	uint16_t u16dungeon_tid = 0;
	uint8_t u8difficulty = 0;

	* pPacket >> u32room_number >> u16dungeon_tid >> u8difficulty;

	NLogic::Static::PARTYROOMTREE & clsPartyRoomTree = NLogic::Static::Instance().GETPARTYROOMTREE();
	auto itrs = clsPartyRoomTree.find( NLogic::Key(u16dungeon_tid, u8difficulty) );
	if (itrs == clsPartyRoomTree.end())
	{
		SendAckFail(pUser, ACK_NOT_PARTY);
		return;
	}

	NLogic::Static::SPACEVECTOR & spaceVector = itrs->second;
	//NLogic::Static::SPACEVECTOR & spaceVector = NLogic::Static::Instance().GETPARTYROOMTREE().find(NLogic::Key(u16dungeon_tid, u8difficulty));
	if (spaceVector.size() <= 0)
	{
		SendAckFail(pUser, ACK_NOT_PARTY);
		return;
	}

	int level = pUser->GetCharacterInfo().level;
	NResource::DungeonEnterLimitLevel * pDungeonEnterLimitLevel = NResource::Static::Instance().GetDungeonEnterLimitLevel();
	if (NULL == pDungeonEnterLimitLevel)
	{
		SendAckFail(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int limitLevel = pDungeonEnterLimitLevel->GetLevel(u16dungeon_tid);
	if (level < limitLevel)
	{
		SendAckFail(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Space * pNewPartyRoom = NULL;

	auto itr = spaceVector.begin();
	for ( ;itr != spaceVector.end(); ++itr)
	{
		NLogic::Space * pExistPartyRoom = ( * itr );

		NLogic::Indexer * pIndexer = pExistPartyRoom->GetIndexer();
		if (NULL == pIndexer)
			continue;

		if (static_cast<uint32_t>(pExistPartyRoom->GetIndexer()->GetIndex()) == u32room_number)
		{
			pNewPartyRoom = pExistPartyRoom;
			break;
		}
	}

	if (NULL == pNewPartyRoom)
	{
		SendAckFail(pUser, ACK_NOT_PARTY);
		return;
	}

	NLogic::Party * pParty = pNewPartyRoom->GetParty();
	if (NULL == pParty)
	{
		SendAckFail(pUser, ACK_NOT_PARTY);
		return;
	}

	if (NLogic::Party::State::NEW_PARTY_ROOM_WAIT != pParty->GetState())
	{
		SendAckFail(pUser, ACK_START_BATTLE);
		return;
	}

	if (static_cast<int>(pParty->GetAllUserTree().size()) >= pNewPartyRoom->GetData()._maxUser + 1)
	{
		SendAckFail(pUser, ACK_START_BATTLE);
		return;
	}

	pParty->EnterUser(pUser);
	//pParty->AddAcceptUserTree(pUser);
	pParty->AddInviteUserTree(pUser);

//	if (pParty->GetInviteUserTree().size() < pNewPartyRoom->GetData()._maxUser)
//	{
//		return;
//	}

	User * pMaster = pParty->GetMaster();
	if (NULL == pMaster)
	{
		SendAckFail(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	auto partyAllUserTree = pParty->GetAllUserTree();

	::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
	* pNoti << pUser->GetUserSeq();
	pNoti->MakePacket(CMD_SN_REQ_DUNGEON_PARTY_JOIN);
	pNewPartyRoom->SendAll(pNoti);

	pWorld->LeaveUser(pUser);
	pNewPartyRoom->EnterUser(pUser);

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	* pAck << static_cast<int16_t>(ACK_OK);
	* pAck << static_cast<uint32_t>(pNewPartyRoom->GetIndexer()->GetIndex());
	* pAck << static_cast<uint8_t>(pNewPartyRoom->GetData()._maxUser);

	uint8_t count = partyAllUserTree.size();

	uint32_t u32gid = static_cast<uint32_t>(pMaster->GetUserSeq());
	* pAck << static_cast<uint8_t>(count);
	* pAck << u32gid;

	std::for_each(partyAllUserTree.begin(), partyAllUserTree.end(), [&](NLogic::Party::USERTREE::value_type & pair) {
		User * pUser = pair.second;

		if ( pUser != pMaster)
		{
			uint32_t u32gid = static_cast<uint32_t>(pUser->GetUserSeq());

			* pAck << u32gid;
		}
	} );

	pAck->MakePacket(CMD_SC_REQ_DUNGEON_PARTY_JOIN);
	pUser->Send(pAck);

	::Network::Packet * pDungeonInfo = pNewPartyRoom->GetDetailInfoPacket();
	if (NULL != pDungeonInfo)
	{
		::Network::Packet * pDungeonInfoNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
		pDungeonInfoNoti->WriteBin(pDungeonInfo->GetPtr()+6, pDungeonInfo->GetEndLen()-6);
		pDungeonInfoNoti->MakePacket(CMD_SN_DUNGEON_DETAIL_INFO);
		pUser->Send(pDungeonInfoNoti);
	}
	pUser->SetEnumState(User::EnumState::ACCEPT_WAIT);


//	if (count < pNewPartyRoom->GetData()._maxUser)
//	{
//		return;
//	}
//
//	::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
//	* pNoti << static_cast<int16_t>(ACK_OK);
//	* pNoti << static_cast<uint8_t>(pParty->GetAllUserTree().size());
//	//* pNoti << pMaster->GetUserInfo().userseq;
//
//	std::for_each(partyAllUserTree.begin(), partyAllUserTree.end(), [&](NLogic::Party::USERTREE::value_type & pair) {
//		User * pUser = pair.second;
//
//		uint32_t u32gid = static_cast<uint32_t>(pUser->GetUserSeq());
//
//		* pNoti << u32gid;
//
//		pUser->SetEnumState(User::EnumState::READY_WAIT);
//	} );
//
//	pNoti->MakePacket(CMD_SN_PARTY_CREATE_DONE);
//
//	pNewPartyRoom->SendAll(pNoti);
//
//	pParty->SetState(NLogic::Party::State::READY_WAIT);
}

} /*NCommand*/ } /*ProjectZ*/
